package com.example.videocollection

import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.graphics.ImageFormat
import android.graphics.SurfaceTexture
import android.hardware.camera2.*
import android.hardware.camera2.params.StreamConfigurationMap
import android.media.ImageReader
import android.os.Bundle
import android.os.Handler
import android.os.HandlerThread
import android.util.Log
import android.util.Range
import android.util.Size
import android.view.Surface
import android.view.TextureView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import com.example.videocollection.Util.getBestSupportedSize
import kotlin.collections.ArrayList
import kotlin.math.max
import kotlin.math.min
import kotlin.system.exitProcess

/** 后摄像头 */
private const val CAMERA_BACK = "0"

/** 前摄像头 */
private const val CAMERA_FRONT = "1"

/** 请求权限码 */
private const val REQUEST_PERMISSION_CODE = 1

/** TAG */
private const val TAG = "VideoCollection"


/**
 * 实现视频画面采集、预览
 *
 * @author just1296
 * @since 2021-10-22
 */
class MainActivity : AppCompatActivity(), TextureView.SurfaceTextureListener, ImageReader.OnImageAvailableListener {

    /** 权限组 */
    private val permissions: Array<String> = arrayOf(Manifest.permission.CAMERA)

    /** 预览 */
    private val previewTexture: TextureView by lazy { findViewById(R.id.video_preview) }

    /** 最小帧率 */
    private var minFps: Int = 15

    /** 最大帧率 */
    private var maxFps: Int = 60

    /** 当前帧率的范围 */
    private var curFpsRange: Range<Int>? = null

    /** 预览尺寸 */
    private var previewSize: Size? = null

    /** 图片阅读器 */
    private lateinit var imageReader: ImageReader

    /** 后台线程Handler */
    private var backgroundHandler: Handler? = null

    /** 摄像头 */
    private var cameraDevice: CameraDevice? = null

    /** 预览配置构造器 */
    private var previewRequestBuilder: CaptureRequest.Builder? = null

    /** 预览会话 */
    private var captureSession: CameraCaptureSession? = null

    /** 摄像头设备状态回调 */
    private val deviceStateCallback = object : CameraDevice.StateCallback() {
        override fun onOpened(camera: CameraDevice) {
            cameraDevice = camera
            createCameraPreviewSession()
        }

        override fun onDisconnected(camera: CameraDevice) {
            camera.close()
            cameraDevice = null
        }

        override fun onError(camera: CameraDevice, error: Int) {
            camera.close()
            cameraDevice = null
        }
    }

    /** 预览回调 */
    private val captureStateCallback = object : CameraCaptureSession.StateCallback() {
        override fun onConfigured(session: CameraCaptureSession) {
            val previewRequest = previewRequestBuilder?.build() ?: return
            captureSession = session
            try {
                captureSession?.setRepeatingRequest(previewRequest, object : CameraCaptureSession.CaptureCallback() {},
                        backgroundHandler)
            } catch (e: Exception) {
                Log.e(TAG, e.message.toString())
            }
        }

        override fun onConfigureFailed(session: CameraCaptureSession) {

        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager
                        .PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, permissions, REQUEST_PERMISSION_CODE)
        }
        previewTexture.surfaceTextureListener = this
    }

    override fun onSurfaceTextureAvailable(surface: SurfaceTexture, width: Int, height: Int) {
        startVideoCollection()
    }

    override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture, width: Int, height: Int) {

    }

    override fun onSurfaceTextureDestroyed(surface: SurfaceTexture): Boolean {
        return false
    }

    override fun onSurfaceTextureUpdated(surface: SurfaceTexture) {

    }

    /**
     * 开始视频采集
     */
    private fun startVideoCollection() {
        // 1、获取摄像头管理器
        val cameraManager = getSystemService(Context.CAMERA_SERVICE) as CameraManager
        // 2、获取后摄像头配置信息
        val characteristics = cameraManager.getCameraCharacteristics(CAMERA_BACK)
        // 获取最适应帧率
        val fpsRanges: Array<Range<Int>> = characteristics.get(CameraCharacteristics
                .CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES) as Array<Range<Int>>
        for (fps in fpsRanges) {
            Log.d(TAG, "fpsRanges = $fps")
            // 帧率范围超过[15, 60]，则使用[15, 60]
            if (minFps >= fps.lower && maxFps <= fps.upper) {
                curFpsRange = Range(minFps, maxFps)
                break
            }
            // 计算权重，采用差值平方来比较
            val weight = (fps.lower - minFps) * (fps.lower - minFps) + (fps.upper - maxFps) * (fps.upper - maxFps)
            if (weight < Int.MAX_VALUE) {
                Log.d(TAG, "fpsRanges = ${max(fps.lower, minFps)}, ${min(fps.upper, maxFps)}")
                curFpsRange = Range(max(fps.lower, minFps), min(fps.upper, maxFps))
            }
        }
        // 获取格式
        val map: StreamConfigurationMap = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
                ?: return
        val list = ArrayList<Size>()
        val outputSizes = map.getOutputSizes(SurfaceTexture::class.java)
        for (size in outputSizes) {
            list.add(size)
        }
        previewSize = getBestSupportedSize(list)
        Log.d(TAG, "previewSize width = ${previewSize?.width}; height = ${previewSize?.height}")
        imageReader = ImageReader.newInstance(previewSize!!.width, previewSize!!.height, ImageFormat.YUV_420_888, 2)
        imageReader.setOnImageAvailableListener(this, backgroundHandler)
        val backgroundThread = HandlerThread("CameraBackground")
        backgroundThread.start()
        backgroundHandler = Handler(backgroundThread.looper)
        // 检查相机权限
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager
                        .PERMISSION_GRANTED) {
            return
        }
        // 3、打开摄像头
        cameraManager.openCamera(CAMERA_BACK,deviceStateCallback ,backgroundHandler)
    }


    /**
     * 创建摄像头预览会话
     */
    private fun createCameraPreviewSession() {
        val previewWidth = previewSize?.width ?: resources.displayMetrics.widthPixels
        val previewHeight = previewSize?.height ?: resources.displayMetrics.heightPixels
        val surfaceTexture = previewTexture.surfaceTexture
        // 设置预览
        surfaceTexture?.setDefaultBufferSize(previewWidth, previewHeight)
        try {// 创建一个Surface
            val surface = Surface(surfaceTexture)
            previewRequestBuilder = cameraDevice?.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)
            // 设置帧率
            previewRequestBuilder?.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, curFpsRange)
            // 设置预览的surface
            previewRequestBuilder?.addTarget(surface)
            previewRequestBuilder?.addTarget(imageReader.surface)
            // 开始预览
            cameraDevice?.createCaptureSession(listOf(surface, imageReader.surface), captureStateCallback,
                    backgroundHandler)
        } catch (e: Exception) {
            Log.e(TAG, e.message.toString())
        }
    }

    override fun onImageAvailable(reader: ImageReader?) {
        // 刷新每一帧数据到画面上
        val image = reader?.acquireNextImage()
        image?.close()
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == REQUEST_PERMISSION_CODE) {
            for (result in grantResults) {
                if (result != PackageManager.PERMISSION_GRANTED) {
                    exitProcess(0)
                }
            }
            startVideoCollection()
        }
    }
}